package cn.yzgy.yzgyoa.common.utils;

import cn.yzgy.yzgyoa.common.entity.SysLog;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 日志敏感信息脱敏和插入数据库
 *
 * @author Yqsen
 * @since 2019-12-17 11:36:09
 */
@Slf4j
@Component
public class LogSensitiveInfoUtil {

    private static final String REPLACE_STRING = "*****数据已脱敏*****";

    /**
     * 需要过滤的URI
     */
    private static final List<String> SENSITIVE_URI_LIST = new ArrayList<String>() {{
        add("ucenter/login");
    }};

    /**
     * 需要过滤的节点
     */
    private static final List<String> SENSITIVE_NODE_LIST = new ArrayList<String>() {{
        add("psw");
        add("token");
    }};

    /**
     * 替换掉敏感信息后插入数据库记录
     *
     * @param sysLog 日志对象
     */
    @Async
    public void insert(SysLog sysLog) {
        if (sysLog.isNeedLog()) {
            SENSITIVE_URI_LIST.forEach(x -> {
                if (sysLog.getUrl().contains(x)) {
                    SENSITIVE_NODE_LIST.forEach(y -> {
                        sysLog.setRequestArgs(removeSensitiveInfo(sysLog.getRequestArgs(), y));
                        sysLog.setResponse(removeSensitiveInfo(sysLog.getResponse(), y));
                    });
                }
            });
            sysLog.insert();
        }
    }

    /**
     * 替换JSON中的指定key的值为上边定义的字串
     *
     * @param src 原始请求数据JSON格式
     * @param key 要替换的key
     * @return 将key中的敏感数据替换为上边定义数据后的数据
     */
    private String removeSensitiveInfo(String src, String key) {
        JSONObject obj = JSON.parseObject(src);
        globalReplaceKey(obj,key);
        return obj.toJSONString();
    }

    /**
     * 递归查找并替换Key
     *
     * @param object 原始JSON对象
     * @param key 要替换的key
     */
    private void globalReplaceKey(JSONObject object, String key) {
        object.entrySet().forEach(x -> {
            if (x.getKey().equals(key)) {
                x.setValue(REPLACE_STRING);
            } else if (x.getValue() instanceof JSONObject) {
                globalReplaceKey((JSONObject) x.getValue(),key);
            }
        });
    }
}
